package com.zhudi.math;

import com.ruoyi.common.exception.BusinessException;
import com.zhudi.utils.MathUtil;

import java.math.BigDecimal;

/**
 * 计算TopSis模型
 * @author chongjin
 */
public class TopSis {

    public static BigDecimal[] getTopSis(BigDecimal[][] standard, BigDecimal[] comprehensiveData) {
        if (null == standard || standard.length == 0 || standard[0].length == 0) {
            throw new BusinessException("标准化矩阵为空");
        }
        if (null == comprehensiveData || comprehensiveData.length == 0) {
            throw new BusinessException("综合权重向量为空");
        }
        if (standard[0].length != comprehensiveData.length) {
            throw new BusinessException("标准化矩阵和综合权重向量长度不一致");
        }
        //构建加权规范化矩阵
        BigDecimal[][] canonical = new BigDecimal[standard.length][standard[0].length];
        BigDecimal[][] param = new BigDecimal[2][standard[0].length];
        BigDecimal max = null;
        BigDecimal min = null;
        BigDecimal sumPositive = null;
        BigDecimal sumNegative = null;
        for (int j = 0; j < standard[0].length; j++) {
            max = BigDecimal.ZERO;
            min = MathUtil.MAX;
            for (int i = 0; i < standard.length; i++) {
                //标准化矩阵与综合权重向量相乘 给加权规范化矩阵赋值
                canonical[i][j] = standard[i][j].multiply(comprehensiveData[j]);
                //找出最大值和最小值，正负理想解
                max = max.compareTo(canonical[i][j]) > 0 ? max : canonical[i][j];
                min = min.compareTo(canonical[i][j]) < 0 ? min : canonical[i][j];
            }
            param[0][j] = max;
            param[1][j] = min;
        }
        BigDecimal[] resultData = new BigDecimal[standard.length];
        BigDecimal closer = null;
        BigDecimal sumCloser = BigDecimal.ZERO;
        for (int i = 0; i < canonical.length; i++) {
            sumPositive = BigDecimal.ZERO;
            sumNegative = BigDecimal.ZERO;
            for (int j = 0; j < canonical[0].length; j++) {
                //平方和累加
                sumPositive = sumPositive.add(canonical[i][j].subtract(param[0][j]).pow(2));
                sumNegative = sumNegative.add(canonical[i][j].subtract(param[1][j]).pow(2));
            }
            //开方得正、负理想解之间的欧式距离
            sumPositive = MathUtil.getSqrt(sumPositive);
            sumNegative = MathUtil.getSqrt(sumNegative);
            closer = sumNegative.divide(sumPositive.add(sumNegative), 4, BigDecimal.ROUND_HALF_UP);
            resultData[i] = closer;
            //累加，准备归一化处理
            sumCloser = sumCloser.add(closer);
        }
        for (int i = 0; i < canonical.length; i++) {
            //归一化
            resultData[i] = resultData[i].divide(sumCloser, 4, BigDecimal.ROUND_HALF_UP);
        }
        return resultData;
    }
}
